Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports System.Timers
Imports System.Windows.Threading


Public Enum SearchMode
	Instant
	Delayed
End Enum

Public Class SearchTextBox
	Inherits TextBox

	Public Shared LabelTextProperty As DependencyProperty = DependencyProperty.Register("LabelText", GetType(String), GetType(SearchTextBox))

	Public Shared LabelTextColorProperty As DependencyProperty = DependencyProperty.Register("LabelTextColor", GetType(Brush), GetType(SearchTextBox))

	Public Shared SearchModeProperty As DependencyProperty = DependencyProperty.Register("SearchMode", GetType(SearchMode), GetType(SearchTextBox), New PropertyMetadata(SearchMode.Instant))

	Private Shared HasTextPropertyKey As DependencyPropertyKey = DependencyProperty.RegisterReadOnly("HasText", GetType(Boolean), GetType(SearchTextBox), New PropertyMetadata())
	Public Shared HasTextProperty As DependencyProperty = HasTextPropertyKey.DependencyProperty

	Private Shared IsMouseLeftButtonDownPropertyKey As DependencyPropertyKey = DependencyProperty.RegisterReadOnly("IsMouseLeftButtonDown", GetType(Boolean), GetType(SearchTextBox), New PropertyMetadata())
	Public Shared IsMouseLeftButtonDownProperty As DependencyProperty = IsMouseLeftButtonDownPropertyKey.DependencyProperty

    'Public Shared SearchEventTimeDelayProperty As DependencyProperty = DependencyProperty.Register("SearchEventTimeDelay", GetType(Duration), GetType(SearchTextBox), New FrameworkPropertyMetadata(New Duration(New TimeSpan(0, 0, 0, 0, 500)), New PropertyChangedCallback(OnSearchEventTimeDelayChanged()))

	Public Shared ReadOnly SearchEvent As RoutedEvent = EventManager.RegisterRoutedEvent("Search", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(SearchTextBox))

	Shared Sub New()
        DefaultStyleKeyProperty.OverrideMetadata(GetType(SearchTextBox), New FrameworkPropertyMetadata(GetType(SearchTextBox)))
	End Sub


	Public Sub New()
		MyBase.New()
    End Sub

    Protected Overrides Sub OnTextChanged(ByVal e As TextChangedEventArgs)
        MyBase.OnTextChanged(e)

        HasText = Text.Length <> 0
    End Sub

	Public Overrides Sub OnApplyTemplate()
		MyBase.OnApplyTemplate()

		Dim iconBorder As Border = TryCast(GetTemplateChild("PART_SearchIconBorder"), Border)
		If iconBorder IsNot Nothing Then
			AddHandler iconBorder.MouseLeftButtonDown, New MouseButtonEventHandler(AddressOf IconBorder_MouseLeftButtonDown)
			AddHandler iconBorder.MouseLeftButtonUp, New MouseButtonEventHandler(AddressOf IconBorder_MouseLeftButtonUp)
			AddHandler iconBorder.MouseLeave, New MouseEventHandler(AddressOf IconBorder_MouseLeave)
		End If
	End Sub

	Private Sub IconBorder_MouseLeftButtonDown(obj As Object, e As MouseButtonEventArgs)
		IsMouseLeftButtonDown = True
	End Sub

	Private Sub IconBorder_MouseLeftButtonUp(obj As Object, e As MouseButtonEventArgs)
		If Not IsMouseLeftButtonDown Then
			Return
		End If

		If HasText AndAlso SearchMode = SearchMode.Instant Then
			Me.Text = ""
		End If

		If HasText AndAlso SearchMode = SearchMode.Delayed Then
			RaiseSearchEvent()
		End If

		IsMouseLeftButtonDown = False
	End Sub

	Private Sub IconBorder_MouseLeave(obj As Object, e As MouseEventArgs)
		IsMouseLeftButtonDown = False
	End Sub

	Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
		If e.Key = Key.Escape AndAlso SearchMode = SearchMode.Instant Then
			Me.Text = ""
        ElseIf (e.Key = Key.[Return] OrElse e.Key = Key.Enter) AndAlso SearchMode = SearchMode.Instant Then
            RaiseSearchEvent()
		Else
			MyBase.OnKeyDown(e)
		End If
	End Sub

	Private Sub RaiseSearchEvent()
		Dim args As New RoutedEventArgs(SearchEvent)
        MyBase.RaiseEvent(args)
	End Sub

	Public Property LabelText() As String
		Get
			Return DirectCast(GetValue(LabelTextProperty), String)
		End Get
		Set
			SetValue(LabelTextProperty, value)
		End Set
	End Property

	Public Property LabelTextColor() As Brush
		Get
			Return DirectCast(GetValue(LabelTextColorProperty), Brush)
		End Get
		Set
			SetValue(LabelTextColorProperty, value)
		End Set
	End Property

	Public Property SearchMode() As SearchMode
		Get
			Return CType(GetValue(SearchModeProperty), SearchMode)
		End Get
		Set
			SetValue(SearchModeProperty, value)
		End Set
	End Property

	Public Property HasText() As Boolean
		Get
			Return CBool(GetValue(HasTextProperty))
		End Get
		Private Set
			SetValue(HasTextPropertyKey, value)
		End Set
	End Property

	Public Property IsMouseLeftButtonDown() As Boolean
		Get
			Return CBool(GetValue(IsMouseLeftButtonDownProperty))
		End Get
		Private Set
			SetValue(IsMouseLeftButtonDownPropertyKey, value)
		End Set
	End Property

	Public Custom Event Search As RoutedEventHandler
        AddHandler(ByVal value As RoutedEventHandler)
            [AddHandler](SearchEvent, value)
        End AddHandler
		RemoveHandler(ByVal value As RoutedEventHandler)
			[RemoveHandler](SearchEvent, value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Me.RaiseEvent(e)
        End RaiseEvent
    End Event
End Class
